package cac.fenjian.resource.materialreceipt.service;

import cac.common.CallInterFace.service.CallInterfaceService;
import cac.common.CreatMsgId;
import cac.common.CreateCommonLog;
import cac.common.DateUtil;
import cac.fenjian.resource.AoTask.MsAoMatchInfo.dao.MsAoMatchInfoDao;
import cac.fenjian.resource.AoTask.MsAoMatchInfo.dto.MsAoMatchInfoDTO;
import cac.fenjian.resource.AoTask.MsTaskAo.dao.MsTaskAoDao;
import cac.fenjian.resource.AoTask.MsTaskPackage.dao.MsTaskPackageDao;
import cac.fenjian.resource.AoTask.MsTaskPackage.service.MsTaskCheckOperService;
import cac.fenjian.resource.AoTask.MsWorkbinMaterial.dao.MsWorkbinMaterialDao;
import cac.fenjian.resource.AoTask.MsWorkbinMaterial.dao.MsWorkbinRuleDao;
import cac.fenjian.resource.AoTask.MsWorkbinMaterial.dto.MsWorkbinMaterialDTO;
import cac.fenjian.resource.PointPackageSort.dao.PointPackageDao;
import cac.fenjian.resource.WmsDeliverPlan.dto.WmsDeliverPlanDTO;
import cac.fenjian.resource.finProReceiveSearch.service.FinProReceiveSearchService;
import cac.fenjian.resource.materialreceipt.dao.WmsInvInBillHDao;
import cac.fenjian.resource.materialreceipt.dao.WmsInvInBillLDao;
import cac.fenjian.resource.materialreceipt.dao.WmsItemInventoryDao;
import cac.fenjian.resource.materialreceipt.util.AsyncLog;
import cac.fenjian.resource.materialreceipt.util.MaterialReceiptSyn;
import cac.fenjian.resource.materialreceipt.util.MaterialReceiptUtil;
import cac.fenjian.resource.mssslshelves.dao.MsSslShelvesDao;
import cac.fenjian.resource.mssslshelves.service.MsSslShelvesService;
import cac.fenjian.resource.outBill.service.WmsInvOutBillService;
import cac.fenjian.resource.outStoreroom.dao.OutStoreroomDao;
import cac.fenjian.resource.partreceivesearch.service.PartReceiveService;
import cac.fenjian.resource.wmsdeliverplan.dao.WmsDeliverPlanDao;
import cac.gkinterface.service.WorkService;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.cac.dme.adapter.rest.msg.ResponseMsg;
import com.cac.dme.adapter.utils.ComUtil;
import com.cac.dme.common.exception.service.DaoException;
import com.github.pagehelper.PageHelper;
import lombok.extern.slf4j.Slf4j;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.core.env.Environment;
import org.springframework.scheduling.annotation.Async;
import org.springframework.stereotype.Service;
import org.springframework.transaction.PlatformTransactionManager;
import org.springframework.transaction.TransactionDefinition;
import org.springframework.transaction.TransactionStatus;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.transaction.interceptor.TransactionAspectSupport;

import java.text.ParseException;
import java.util.*;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;

@Service
@Slf4j
public class MaterialReceiptService {

    private Logger log = LoggerFactory.getLogger(MaterialReceiptService.class);

    @Autowired
    private WmsInvInBillHDao wmsInvInBillHDao;

    @Autowired
    private WmsInvInBillLDao wmsInvInBillLDao;

    @Autowired
    private WmsDeliverPlanDao wmsDeliverPlanDao;

    @Autowired
    private WmsItemInventoryDao wmsItemInventoryDao;
    @Autowired
    private MsWorkbinMaterialDao msWorkbinMaterialDao;
    @Autowired
    private MsSslShelvesDao msSslShelvesDao;
    @Autowired
    private MsAoMatchInfoDao msAoMatchInfoDao;
    @Autowired
    private Environment environment;
    @Autowired
    private CallInterfaceService callInterfaceService;
    @Autowired
    private PlatformTransactionManager platformTransactionManager;
    @Autowired
    private WorkService workService;
    @Autowired
    private MaterialReceiptSyn materialReceiptSyn;
    @Autowired
    private TransactionDefinition transactionDefinition;
    @Autowired
    private MsTaskAoDao msTaskAoDao;
    @Autowired
    private MsTaskPackageDao msTaskPackageDao;
    @Autowired
    private WmsInvOutBillService wmsInvOutBillService;
    @Autowired
    private OutStoreroomDao outStoreroomDao;
    @Autowired
    private CreateCommonLog createCommonLog;
    @Autowired
    private MsSslShelvesService msSslShelvesService;
    @Autowired
    private PointPackageDao pointPackageDao;
    @Autowired
    private AsyncLog asyncLog;

    private Lock lock = new ReentrantLock();

    /**
     * 物料入库叫箱功能
     *
     * @param map
     * @return
     */
    public List<HashMap<String, Object>> materialReceiptCallCase(Map map) {
        List<String> itemCodes = (List<String>) map.get("itemCodes");
        List<HashMap<String, Object>> sqlRetrun = new ArrayList<>();
        for (String itemCode : itemCodes
        ) {
            sqlRetrun.addAll(msSslShelvesDao.getShelvesCodeByWorkbinCode(itemCode));
        }
        return sqlRetrun;
    }

    /**
     * 根据物料条码，物料箱编码，选择插入入库申请单主表、子表、物料箱信息
     *
     * @param
     * @return 数据库返回
     */

    public ResponseMsg materialReceipt(List<WmsDeliverPlanDTO> planDTOs, String workbinCode, String departid, String account, String IP, String shop) {
        ResponseMsg responseMsg = new ResponseMsg();
        for (Object o : planDTOs) {
            //判断当前入库的交接单是不是入库人相关单位的
            WmsDeliverPlanDTO d = JSONObject.parseObject(JSON.toJSONString(o), WmsDeliverPlanDTO.class);
            int cnt = wmsDeliverPlanDao.checkInstoreMaterialShop(d.getWmsDeliveryPlanId(), shop);
            if (cnt == 0) {
                return responseMsg.setRetCode("201").setMessage("当前登录人单位与接收物料单位不一致");
            }
            wmsDeliverPlanDao.updateMsWorkbinReceDetail(workbinCode, d);
        }

        TransactionStatus transaction = platformTransactionManager.getTransaction(transactionDefinition);
        try {
            for (Object DTO : planDTOs) {
                String jsonObject = JSON.toJSONString(DTO);
                WmsDeliverPlanDTO planDTO = JSONObject.parseObject(jsonObject, WmsDeliverPlanDTO.class);
                if (planDTO.getStorageQty() != 0) {
                    //入库申请单主表id
                    String WmsInvInBillHId = ComUtil.getId();
                    // 入库申请单字表id
//                    String WmsInvInBillLId = ComUtil.getId();
                    //台账表id
                    //查询台账是否存在该交接单信息
                    String WmsItemInventoryId = msWorkbinMaterialDao.isDelivery(planDTO);
                    if (WmsItemInventoryId == null) {
                        WmsItemInventoryId = ComUtil.getId();
                    }
                    //台账表id
//                //根据barcode查询出移交表中数据信息
//                WmsDeliverPlanDTO wmsDeliverPlanDTO = wmsDeliverPlanDao.searchDeliverPlan(barcode);
                    //数据插入入库申请表主表
                    wmsInvInBillHDao.insertWmsInvInBillH(planDTO, WmsInvInBillHId, departid, account);
                    //数据插入入库申请表字表
                    wmsInvInBillLDao.insertWmsInvInBillL(planDTO, WmsInvInBillHId, departid, account);
                    //数据插入台账表
                    wmsItemInventoryDao.insertWmsItemInventory(planDTO, WmsItemInventoryId, DateUtil.nowTime(), departid, account);
                    //2023-03-07 yebo 数据插入库存事务流水表
                    wmsItemInventoryDao.insertWmsItemTransaction(planDTO, WmsItemInventoryId, WmsInvInBillHId);
                    //数据绑定进缓存箱
                    msWorkbinMaterialDao.bindingMsWorkbinMaterial(planDTO, WmsItemInventoryId, workbinCode);
                    //更新移交表信息
                    wmsDeliverPlanDao.updatePlanDto(planDTO);
                    //修改叫箱配置表，is_del字段为Y
                    wmsDeliverPlanDao.updateMsWorkbinReceDetail(workbinCode, planDTO);
                    //修改交接单状态为已入库
                    wmsDeliverPlanDao.updateDeliveryStatus(planDTO);
                    //修改货架空箱状态
                    msSslShelvesDao.updateIsEmpty(workbinCode);

                    int deliveryQty = wmsDeliverPlanDao.queryDeliveryQtyFromWmsDelivery(planDTO);

                    /**
                     * 接收完成后，向ERP传输接收信号
                     */

                    int rsl = wmsDeliverPlanDao.searchIsFinish(planDTO);
                    log.info("2023-11-15----yebo添加日志输出-----入库1---判断是否完全入库,rsl:" + rsl + "---交接单ID：" + planDTO.getWmsDeliveryPlanId() + "----WmsItemInventoryId:" + WmsItemInventoryId);
                    if (rsl != 6) {
                        continue;
                    }
                    log.info("2023-11-15-----yebo添加日志输出-----入库2--准备异步调用推送台账----交接单ID：" + planDTO.getWmsDeliveryPlanId() + "---WmsItemInventoryId:" + WmsItemInventoryId);
                    HashMap aLog = new HashMap();
                    aLog.put("businessVal", WmsItemInventoryId);
                    aLog.put("busniessCol", "wms_item_inventory_id");
                    aLog.put("taskName", "WMS推送台账");
                    aLog.put("taskType", "scanRecieveXX");
                    asyncLog.insertAsyncLog(aLog);
                    //yebo 更改为异步调用推送台账给ERP
                    materialReceiptSyn.sendItemInventoryToErpSyn(planDTO, WmsItemInventoryId, account, IP);
                }
            }
            //全部成功提交事务
            platformTransactionManager.commit(transaction);
            return responseMsg.setMessage("物料入库成功且向ERP发送数据成功！").setRetCode("200");
        } catch (Exception e) {
            //有一个失败，回滚事务
            log.info("物料入库程序异常：" + e.getMessage());
            platformTransactionManager.rollback(transaction);
            e.printStackTrace();
            return responseMsg.setRetCode("201").setMessage("程序异常，请联系开发人员！");
        } finally {
            return responseMsg;
        }
    }

    //判断退库接收状态
    public String searchPlanRet(List<WmsDeliverPlanDTO> planDTOs) {
        try {
            String wmsDeliverPlanDTOS = null;
            for (Object DTO : planDTOs) {
                String jsonObject = JSON.toJSONString(DTO);
                WmsDeliverPlanDTO planDTO = JSONObject.parseObject(jsonObject, WmsDeliverPlanDTO.class);
                wmsDeliverPlanDTOS = wmsDeliverPlanDao.searchPlanRet(planDTO);
            }
            return wmsDeliverPlanDTOS;
        } catch (Exception e) {
            e.printStackTrace();
            return "201";
        }
    }

    //退库接收之后进行入库
    public ResponseMsg updateWmsItemInventory(List<WmsDeliverPlanDTO> planDTOs, String workbinCode, String account, String IP) {
        ResponseMsg responseMsg = new ResponseMsg();
        TransactionStatus transaction = platformTransactionManager.getTransaction(transactionDefinition);
        HashMap senBData = new HashMap();
        JSONObject headersMap = new JSONObject();
        try {
            for (Object DTO : planDTOs) {
                String jsonObject = JSON.toJSONString(DTO);
                WmsDeliverPlanDTO planDTO = JSONObject.parseObject(jsonObject, WmsDeliverPlanDTO.class);
                //更新台账表物料数量信息
                wmsItemInventoryDao.updateWmsItemInventory(planDTO, workbinCode);
                //查询台账id
                HashMap hashMap1 = wmsItemInventoryDao.searchItemInventory(planDTO);

                String WmsItemInventoryId = (String) hashMap1.get("wmsItemInventoryId");
                String wmsDeliveryPlanId = planDTO.getWmsDeliveryPlanId();
                //绑定缓存箱
                wmsItemInventoryDao.updateInventory(planDTO, workbinCode, WmsItemInventoryId);
                //修改交接单剩余物料数量
                wmsItemInventoryDao.updateDlivery(planDTO);
                //全部入库修改交接单状态
                wmsItemInventoryDao.updateDeliveryStatus(planDTO);
                //修改叫箱配置表，is_del字段为Y
                wmsDeliverPlanDao.updateMsWorkbinReceDetail(workbinCode, planDTO);
                /**
                 * 接收完成后，向ERP传输接收信号
                 */
                int rsl = wmsDeliverPlanDao.searchIsFinish(planDTO);
                if (rsl != 6) {
                    continue;
                }
                //判断是否出库
                int cnt = wmsItemInventoryDao.searchTransaction(WmsItemInventoryId, wmsDeliveryPlanId);
                //查询占用id，合格证
                HashMap param = wmsItemInventoryDao.searchAllotId(WmsItemInventoryId, planDTO.getWmsDeliveryPlanId());
                param.put("opUserCode", account);
                param.put("IP", IP);
                if (cnt > 0) {
                    //撤销出库
                    this.sortInvOutCancle(param);
                    //撤销占用
                    this.sortOccupyCancle(param);
                } else {
                    //撤销占用
                    this.sortOccupyCancle(param);
                }
            }
            //全部成功提交事务
            platformTransactionManager.commit(transaction);

            return responseMsg.setMessage("退库物料再入库成功！").setRetCode("200");
        } catch (Exception e) {
            //有一个失败，回滚事务
            log.info("退库物料入库异常：" + e.getMessage());
            platformTransactionManager.rollback(transaction);
            e.printStackTrace();
            return responseMsg.setRetCode("201").setMessage("程序异常，请联系开发人员！");
        } finally {
            return responseMsg;
        }
    }

//    /**
//     * 根据物料箱编码查询该物料箱中物料信息
//     * @param workbinCode
//     * @return
//     */
//    public List<MsWorkbinMaterialDTO> searchWorkbinMaterial(String workbinCode){
//        List<MsWorkbinMaterialDTO> list =msWorkbinMaterialDao.searchMsWorkbinMaterial(workbinCode);
//        //根据物料箱编码，遍历该物料箱中物料信息
//        for (MsWorkbinMaterialDTO msDto:list
//             ) {
//            //遍历物料箱编码，查询物料数量
//            msDto.setInQty(msWorkbinMaterialDao.searchInQty(msDto.getItemCode()));
//        }
//        return list;
//    }

    /**
     * 根据传入的缓存箱编码查询已接收物料中待入库的数据
     *
     * @param workbinCode
     * @return
     */
    public List<HashMap> searchAwaitStorage(String workbinCode, String IP) {
        try {
            List<HashMap> wmsDeliverPlanDTOS =new ArrayList<>();
            /*
            缓存箱扫码接口
            根据物料箱规则查询当前已移交数据，需要入库放入的缓存箱。
             */
            if (workbinCode.equals("312080030000")) {
                PageHelper.startPage(1, 100);
                wmsDeliverPlanDTOS = wmsDeliverPlanDao.searchByItemCode(workbinCode, IP);
            } else {
                wmsDeliverPlanDTOS = wmsDeliverPlanDao.searchByItemCode(workbinCode, IP);
            }
            return wmsDeliverPlanDTOS;
        } catch (Exception e) {
            e.printStackTrace();
            return null;
        }
    }

    //物料入库扫码时返回大件货物库位号
    public List<HashMap> searchLocatorNo() {
        return wmsDeliverPlanDao.searchLocatorNo();
    }

    /**
     * 根据传入物料箱编码，查询该物料箱中当前工作包任务的物料信息
     *
     * @param map
     * @return
     */
    public List<HashMap> searchInventoryMaterial(Map map) {
        try {
            //根据物料箱编码查询该物料箱已放入的物料编码
            List<HashMap> materialDTOS = msWorkbinMaterialDao.searchMsWorkbinMaterial(map);

            return materialDTOS;
        } catch (Exception e) {
            throw new DaoException(e.getMessage());
        }
    }

//    /**
//     * 分拣出物料到工作包，并且更新缓存箱物料信息
//     *
//     * @param toolCode
//     * @param materialDTOs
//     * @return
//     */
//    public String putToolPackage(String toolCode, List<MsAoMatchInfoDTO> materialDTOs) {
//        TransactionStatus transaction = platformTransactionManager.getTransaction(transactionDefinition);
//        try {
//            for (Object DTO : materialDTOs) {
//                HashMap map = new HashMap();
//                String jsonObject = JSON.toJSONString(DTO);
//                MsAoMatchInfoDTO materialDTO = JSONObject.parseObject(jsonObject, MsAoMatchInfoDTO.class);
//                //插入工作包信息
//                msWorkbinMaterialDao.putToolCode(toolCode, materialDTO);
//                //更新缓存箱信息
//                msWorkbinMaterialDao.updateWorkbin(materialDTO);
//                map.put("ID", materialDTO.getMsAoMatchInfoId());
//                map.put("sortingQty", materialDTO.getOutQty());
//                map.put("outString", null);
//                //更新mcahInfo表
//                msWorkbinMaterialDao.callIsSort(map);
//                log.info(map.get("outString"));
//            }
//            //全部成功提交事务
//            platformTransactionManager.commit(transaction);
//            return "200";
//        } catch (Exception e) {
//            //有一个失败，回滚事务
//            log.info(e.getMessage());
//            platformTransactionManager.rollback(transaction);
//            return e.getMessage();
//        }
//    }

    /**
     * 分拣出物料到工作包，并且更新缓存箱物料信息
     * -v2.0
     *
     * @param toolCode
     * @param materialDTOs
     * @return
     */
    public HashMap putToolPackage(String toolCode, List<HashMap> materialDTOs, String opUserCode, String IP) {
        TransactionStatus transaction = platformTransactionManager.getTransaction(transactionDefinition);
        HashMap result = new HashMap();
        try {
            for (Object DTO : materialDTOs) {
                //创建占用表主键
                String wmsInvOutAllotmentId = ComUtil.getId();
                HashMap map = new HashMap();
                String jsonObject = JSON.toJSONString(DTO);
                HashMap materialDTO = JSONObject.parseObject(jsonObject, HashMap.class);
                //2023-08-16 yebo 新增，修改工作包缓存箱关系表状态
                pointPackageDao.updateWorkbinToolRelStatus(materialDTO);
                //2023-08-26 yebo 新增，修改物料是否带证信息
                pointPackageDao.updateDeliveryIsPaper(materialDTO);
                log.info("分拣详细清单+++++++++++++" + materialDTO.toString());
                //插入工作包信息
                msWorkbinMaterialDao.putToolCode(toolCode, materialDTO);
                String itemQty = msWorkbinMaterialDao.test(materialDTO);
                log.info("【更新缓存箱信息】outQty:" + materialDTO.get("outQty") +
                        ",====wmsItemInventoryId:" + materialDTO.get("wmsItemInventoryId") +
                        ",====workbinCode:" + materialDTO.get("workbinCode") + ",===itemQty:" + itemQty);
                //更新缓存箱信息
                msWorkbinMaterialDao.updateWorkbin(materialDTO);
                map.put("ID", materialDTO.get("msAoMatchInfoId"));
                map.put("sortingQty", materialDTO.get("outQty"));
                map.put("outString", null);
                map.put("wmsInvOutAllotmentId", wmsInvOutAllotmentId);
                log.info((String) map.get("outString"));
                //更新mcahInfo表
                msWorkbinMaterialDao.callIsSort(map);
                //更新台账表
                wmsItemInventoryDao.updateOccupy(materialDTO);

                materialDTO.put("wmsInvOutAllotmentId", wmsInvOutAllotmentId);
                materialDTO.put("ip", IP);
                materialDTO.put("opUserCode", opUserCode);
                //分拣保存时插入占用表
                wmsInvOutBillService.createOutAllotment(materialDTO);
                //分拣占用，所需数据，查询AO_No
                HashMap hashMap = wmsInvOutBillService.sortingAllot(materialDTO);

                HashMap aLog = new HashMap();
                aLog.put("businessVal", wmsInvOutAllotmentId);
                aLog.put("busniessCol", "wms_inv_out_allotment_id");
                aLog.put("taskName", "WMS推送占用");
                aLog.put("taskType", "101-ERP-sortingAllot");
                asyncLog.insertAsyncLog(aLog);
                //异步调用占用信息 2023-10-27 yebo 改为异步的方式
                materialReceiptSyn.sendSortOccupy(opUserCode, IP, hashMap);
                //判断当前AO是否还有物料未分拣
                int isFianlAoMaterail = msAoMatchInfoDao.isNoSortMaterail(materialDTO);
                //部分分拣，增加package标识
                msTaskPackageDao.addSortingRemark((String) materialDTO.get("msTaskAoId"));
                //没有AO存在未分拣物料，表明AO已分拣完成，进入工作包任务中检查是否全部工作包下的AO已分拣完毕
                if (isFianlAoMaterail == 0) {
                    //更新AO分拣状态
                    msTaskAoDao.updateAo((String) materialDTO.get("msTaskAoId"));
                    //查询该AO是否为所属工作包最后一个，是修改工作包状态，否不做操作
                    int isFinalAo = msTaskAoDao.isFinalAo((String) materialDTO.get("msTaskAoId"));
                    //isFinal=0时，证明该ao所属的工作包任务已经分拣完成
                    if (isFinalAo == 0) {
                        //修改工作包任务状态
                        log.info("工作包任务已分拣完成");
                        result.put("msg", "工作包任务已分拣完成");
                        msTaskPackageDao.changePackageStatu((String) materialDTO.get("msTaskAoId"));
                    } else {
                        log.info("工作包任务中任由AO未分拣完成");
                        result.put("msg", "工作包任务中还有AO未分拣完成");
                    }
                } else {
                    //更新AO分拣状态--部分分拣 yebo 2023-08-07
                    msTaskAoDao.updateAoStatusForSome((String) materialDTO.get("msTaskAoId"));
                    //更新AO部分分拣标识
                    log.info("AO物料未全部分拣！");
                    result.put("msg", "AO物料未全部分拣！");
                }

            }
            //yebo 新增保存分拣台操作记录
            //       msTaskCheckOperService.updateMsConsoleOper("hcx","1");
            //全部成功提交事务
            platformTransactionManager.commit(transaction);
            result.put("retCode", "200");
            //分拣保存成功，上传MES分拣状态 2023-10-27 yebo 更改为异步
            materialReceiptSyn.sendSortingMsgToMES();
            return result;
        } catch (Exception e) {
            //有一个失败，回滚事务
            e.printStackTrace();
            platformTransactionManager.rollback(transaction);
            result.put("retCode", "201");
            result.put("msg", "操作失败！");
            return result;
        }
    }


    /**
     * 根据工作包编码查询工作包中物料信息
     *
     * @param toolCode
     * @return
     */
    public List<MsWorkbinMaterialDTO> searchToolMaterial(String toolCode, String func) {
        return msWorkbinMaterialDao.searchMsToolMaterial(toolCode, func);
    }

    /**
     * 根据工作盘编码，查询将要放入的物料信息
     *
     * @param toolCode
     * @return
     */
    public List<HashMap> prestoreMaterial(String toolCode) {
        return msWorkbinMaterialDao.prestoreMaterial(toolCode);
    }

    /**
     * 工艺更改分拣页面，分拣保存功能
     *
     * @param map 传入参数，更改的物料信息
     * @return
     */
    public String changeSorting(HashMap map) {
        TransactionStatus transaction = platformTransactionManager.getTransaction(transactionDefinition);
        try {
            List<HashMap> matchinfos = (List<HashMap>) map.get("materialDTOs");
            for (HashMap machinfo : matchinfos) {
                //1：插入物料缓存箱表信息
                msWorkbinMaterialDao.insertWorkBMaterial(map);
                //2:修改缓存箱数量
                msWorkbinMaterialDao.updateWorkBinMateralQty(map);
                //3：修改台账占用数量
                msWorkbinMaterialDao.updateWmsITemInventory(map);
                //4:修改占用表数据
            }

            //先根据工作包编码，将旧物料数量还给相应缓存料箱
            //第一步：查询出该工具包中的旧物料数据。
            List<MsWorkbinMaterialDTO> oldMaterials = msWorkbinMaterialDao.searchMsToolMaterial((String) map.get("toolCode"), "");
            for (MsWorkbinMaterialDTO dto : oldMaterials) {
                //第二步，根据工作包中具体数据，更新缓存箱中的数量信息。
                msWorkbinMaterialDao.updateItemQty(dto);
            }
            //第三步：删除该工作包数据
            msWorkbinMaterialDao.delByToolCode(map.get("toolCode").toString());
            //第四步：将工艺更改后的对应物料放入工具包
            //插入工作包信息
            List<MsAoMatchInfoDTO> materialDTOs = (List<MsAoMatchInfoDTO>) map.get("materialDTOs");
            for (Object DTO : materialDTOs) {
                String jsonObject = JSON.toJSONString(DTO);
                MsAoMatchInfoDTO materialDTO = JSONObject.parseObject(jsonObject, MsAoMatchInfoDTO.class);
                //插入工作包信息
//                msWorkbinMaterialDao.putToolCode(map.get("toolCode").toString(), materialDTO);
                //更新缓存箱信息
//                msWorkbinMaterialDao.updateWorkbin(materialDTO);
            }
            //全部成功提交事务
            platformTransactionManager.commit(transaction);
            return "200";
        } catch (Exception e) {
            //有一个失败，回滚事务
            log.info(e.getMessage());
            platformTransactionManager.rollback(transaction);
            return e.getMessage();
        }
    }
    /**
     * ------------------------------------------------------
     * end
     * ------------------------------------------------------
     */


    /**
     * ------------------------------------------------------
     * 工具包拆包功能
     * ------------------------------------------------------
     */
    public HashMap toolKitUnpacking(Map map) {
        TransactionStatus transaction = platformTransactionManager.getTransaction(transactionDefinition);
        HashMap result = new HashMap();

        try {
            //获取前端传递的需要拆包的物料信息
            List<HashMap> unpacks = (List<HashMap>) map.get("unpackDto");
            for (HashMap unpack : unpacks) {
                msWorkbinMaterialDao.updateDeleteAndRemoveWorkbinInfo(unpack);//更新缓存箱子物料数量
                msWorkbinMaterialDao.updateUnpackChangeType(unpack);
                msWorkbinMaterialDao.updateInventoryEngQty(unpack);//更新台账占用信息

                //查询占用信息
                List<HashMap> wmsInvOutAllotments = msWorkbinMaterialDao.searchAllotmentIdByinfoId((String) unpack.get("msAoMatchInfoId"));
                for (HashMap wmsInvOutAllotment : wmsInvOutAllotments) {
                    //占用取消
                    HashMap unpackMap = new HashMap();
                    unpackMap.put("opUserCode", map.get("opUserCode"));
                    unpackMap.put("IP", map.get("IP"));
                    unpackMap.put("wmsInvOutAllotmentId", wmsInvOutAllotment.get("wmsInvOutAllotmentId"));
                    unpackMap.put("cancelQty", wmsInvOutAllotment.get("cancelQty"));
                    //分拣占用取消，调用回传ERP
                    String parameters = this.sortOccupyCancle(unpackMap);
                    String code = "sendBData";
                    String name = "两网传输-发送业务数据";
                    String sendScenario = "分拣占用取消";
                    long beginTime = System.currentTimeMillis();
                    log.info("======开始时间=======" + beginTime);
                    callInterfaceService.sendBData(code, name, parameters, sendScenario);
                    long endTime = System.currentTimeMillis();
                    log.info("======消耗时间=======" + (endTime - beginTime) + "ms");
                    //修改占用表状态
                    msWorkbinMaterialDao.cancleAllotmentById(wmsInvOutAllotment.get("wmsInvOutAllotmentId"));
                }
                if ("U".equals(unpack.get("artChangeType"))) { //如果拆包是不完全拆物料，需要重新更新占用信息，并回传ERP
                    //创建占用表主键
                    String wmsInvOutAllotmentId = ComUtil.getId();
                    HashMap outAllotMap = new HashMap();
                    outAllotMap.put("wmsInvOutAllotmentId", wmsInvOutAllotmentId);
                    outAllotMap.put("wmsItemInventoryId", unpack.get("wmsItemInventoryId"));
                    outAllotMap.put("outQty", unpack.get("itemQty"));
                    outAllotMap.put("msTaskAoId", unpack.get("msTaskAoId"));
                    outAllotMap.put("msAoMatchInfoId", unpack.get("msAoMatchInfoId"));
                    outAllotMap.put("opUserCode", map.get("opUserCode"));
                    outAllotMap.put("ip", map.get("IP"));
                    //分拣保存时插入占用表
                    wmsInvOutBillService.createOutAllotment(outAllotMap);
                    //分拣占用，所需数据，查询AO_No
                    HashMap hashMap = wmsInvOutBillService.sortingAllot(outAllotMap);
                    //分拣占用，调用回传ERP
                    String parameters = this.sortOccupy(map.get("opUserCode").toString(), map.get("IP").toString(), hashMap);
                    String code = "sendBData";
                    String name = "两网传输-发送业务数据";
                    String sendScenario = "分拣占用";
                    long beginTime = System.currentTimeMillis();
                    log.info("======开始时间=======" + beginTime);
                    callInterfaceService.sendBData(code, name, parameters, sendScenario);
                    long endTime = System.currentTimeMillis();
                    log.info("======消耗时间=======" + (endTime - beginTime) + "ms");
                }
            }
            //全部成功提交事务
            platformTransactionManager.commit(transaction);
            result.put("retCode", "200");
            result.put("msg", "拆包成功");
        } catch (Exception e) {
            //有一个失败，回滚事务
            e.printStackTrace();
            platformTransactionManager.rollback(transaction);
            result.put("retCode", "201");
            result.put("msg", "拆包失败");
        } finally {
            return result;
        }
    }

    /**
     * 工作包拆包叫箱服务。
     *
     * @param map
     * @return
     */
    public HashMap callToolUnpack(HashMap map) {
        TransactionStatus transaction = platformTransactionManager.getTransaction(transactionDefinition);
        HashMap result = new HashMap();
        StringBuilder retMsg = new StringBuilder();
        try {
            //获取叫箱结束位置
            //获取工作器具包结束位置
            String toolLocation = msSslShelvesService.findStartCode((String) map.get("IP"), "TOOL");
            //获取缓存箱结束位置
            String workBinLocation = msSslShelvesService.findStartCode((String) map.get("IP"), "WORKBIN");
            List<HashMap> unpackInfoList = (List<HashMap>) map.get("unpackInfoList");
            for (int i = 0; i < unpackInfoList.size(); i++) {
                HashMap unpackInfo = unpackInfoList.get(i);
                //查询当前勾选的缓存箱子以及工作包是否存在任务,并且是否在货架上
                int pCnt = msTaskPackageDao.searchExistsTaskAndOnShelves((String) unpackInfo.get("toolCode"));
                if (pCnt == 0) {
                    retMsg.append(unpackInfo.get("toolCode")).append("托盘存在未完成任务或不在货架上");
                    continue;
                }
                int wCnt = msTaskPackageDao.searchExistsTaskAndOnShelves((String) unpackInfo.get("workbinCode"));
                if (wCnt == 0) {
                    retMsg.append(unpackInfo.get("toolCode")).append("缓存箱存在未完成任务或不在货架上");
                    continue;
                }

                //获取对应工作包盘货架位置，下发叫箱任务。
                //下发工作包任务容器
                HashMap toolInformation = new HashMap();
                HashMap toolParam = new HashMap();
                //传入参数中的工作包箱编码
                toolParam.put("workbinCode", unpackInfo.get("toolCode"));
                //获取工作包盘在货架上的具体位置信息
                toolInformation = outStoreroomDao.outStoreroomQuery(toolParam);
                //设置工作包结束位置
                log.info("工作包结束位置" + toolLocation);
                toolInformation.put("endCode", "xyssj" + toolLocation);
                //设置工作包优先级
                toolInformation.put("callPriority", "toolPriority");
                //添加工作包id
                toolInformation.put("packageCode", unpackInfo.get("packageCode"));
                toolInformation.put("command", 1);
                toolInformation.put("taskType", 2);
                toolInformation.put("result", "unpack");
                toolInformation.put("func", "sort");
                //下发工作包任务
                log.info("下发工作包任务" + toolInformation);
                //调用wcs下发任务接口

                createCommonLog.outBound(toolInformation);
                //下发缓存箱盘任务
                //下发缓存箱任务容器
                HashMap workbinInformation = new HashMap();
                HashMap workbinParam = new HashMap();
                workbinParam.put("workbinCode", unpackInfo.get("workbinCode"));
                //获取工作包盘在货架上的具体位置信息
                workbinInformation = outStoreroomDao.outStoreroomQuery(workbinParam);
                //设置工作包结束位置
                workbinInformation.put("endCode", "xyssj" + workBinLocation);
                //设置工作包优先级
                workbinInformation.put("callPriority", "workbinPriority");
                //添加工作包id
                workbinInformation.put("packageCode", unpackInfo.get("packageCode"));
                workbinInformation.put("command", 1);
                workbinInformation.put("taskType", 2);
                workbinInformation.put("result", "unpack");
                workbinInformation.put("func", "sort");
                //添加工作包id
                workbinInformation.put("packageId", unpackInfo.get("msTaskPackageId"));
                //调用wcs下发任务接口
                createCommonLog.outBound(workbinInformation);
            }
            //全部成功提交事务
            platformTransactionManager.commit(transaction);
            //任务下发完成后，启动任务
            HashMap callWcs = new HashMap();
            HashMap data = new HashMap();
            callWcs.put("func", "sort");
            callWcs.put("boxType", "TOOL");
            //工作包结束位置
            callWcs.put("endCode", "xyssj" + toolLocation);
            //调用封装下发任务,接收返回
            data.putAll(createCommonLog.callWCSInterface(callWcs));
            //下发缓存箱出库指令
            callWcs.put("boxType", "WORKBIN");
            //缓存箱结束位置
            callWcs.put("endCode", "xyssj" + workBinLocation);
            //调用封装下发任务
            createCommonLog.callWCSInterface(callWcs);
            //查询该工作包任务所有AO
            data.put("aoCodes", msTaskPackageDao.searchAllAoByPackage(data));
            result.put("retCode", "200");
            result.put("callWCSInterface", data);
            result.put("msg", "工作包拆包叫箱成功！");
        } catch (Exception e) {
            //有一个失败，回滚事务
            log.info(e.getMessage());
            platformTransactionManager.rollback(transaction);
            e.printStackTrace();
            result.put("retCode", "201");
            result.put("msg", "工作包拆包叫箱失败！");
        } finally {
            return result;
        }
    }

    /**
     * ------------------------------------------------------
     * 工具包取消功能
     * ------------------------------------------------------
     */
    /**
     * 工作包取消具体物料数据更新
     *
     * @param map
     * @return
     */
    public String toolKitCancel(Map map) {
        TransactionStatus transaction = platformTransactionManager.getTransaction(transactionDefinition);
        try {
            //先根据工作包编码，将拆包物料数量还给相应缓存料箱
            //第一步：查询出该工具包中的旧物料数据。
            List<MsWorkbinMaterialDTO> oldMaterials = msWorkbinMaterialDao.searchUnpackingMaterial((String) map.get("toolCode"));
            //第二步，根据拆包物料具体数据，更新缓存箱中的数量信息。
            for (MsWorkbinMaterialDTO oldMaterial : oldMaterials) {
                msWorkbinMaterialDao.updateWorkbinCode(oldMaterial, (String) map.get("workbinCode"));
            }
            //第三步：删除该工作包取消的物料信息
            msWorkbinMaterialDao.delByToolCode(map.get("toolCode").toString());
            //全部成功提交事务
            platformTransactionManager.commit(transaction);
            return "200";
        } catch (Exception e) {
            //有一个失败，回滚事务
            log.info(e.getMessage());
            platformTransactionManager.rollback(transaction);
            e.printStackTrace();
            return "201";
        }
    }

    /**
     * 工作包取消叫箱功能接口。
     *
     * @return
     */
    public HashMap callToolKitCancle(HashMap map) {
        TransactionStatus transaction = platformTransactionManager.getTransaction(transactionDefinition);
        HashMap result = new HashMap();
        try {
            //取出传入参数中，工作包箱集合
            List<String> toolKits = (List<String>) map.get("toolKits");
            HashMap sqlRtrun = new HashMap();
            //获取结束位置
            String operationBit = msSslShelvesService.findStartCode((String) map.get("IP"), "TOOL");
            for (String toolKit : toolKits) {
                //获取操作位置编号
                sqlRtrun.put("workbinCode", toolKit);
                sqlRtrun = outStoreroomDao.outStoreroomQuery(sqlRtrun);
                sqlRtrun.put("startCode", "xysjj" + operationBit);
                createCommonLog.outBound(sqlRtrun);
            }
            //全部成功提交事务
            platformTransactionManager.commit(transaction);
            result.put("retCode", "200");
            result.put("msg", "工作包取消叫箱成功！");
        } catch (Exception e) {
            //有一个失败，回滚事务
            log.info(e.getMessage());
            platformTransactionManager.rollback(transaction);
            e.printStackTrace();
            result.put("retCode", "201");
            result.put("msg", "工作包取消叫箱失败！");
            ;
        } finally {
            return result;
        }
    }

    /**
     * ------------------------------------------------------
     * 工具包替换功能
     * ------------------------------------------------------
     */
    public String toolKitReplace(Map map) {
        TransactionStatus transaction = platformTransactionManager.getTransaction(transactionDefinition);
        try {
            //先根据工作包编码，将需要替换的两个工作包判断物料是否一致
            //第一步：查询出该工具包中的旧物料数据。
            List<MsWorkbinMaterialDTO> oldMaterials = msWorkbinMaterialDao.searchMaterialByToolCode((String) map.get("oldToolCode"));
            List<MsWorkbinMaterialDTO> newMaterials = msWorkbinMaterialDao.searchMaterialByToolCode((String) map.get("newToolCode"));
            List<String> oldInId = new ArrayList<>();
            List<String> newInId = new ArrayList<>();
            for (MsWorkbinMaterialDTO old : oldMaterials) {
                oldInId.add(old.getWmsItemInventoryId());
            }
            for (MsWorkbinMaterialDTO replace : newMaterials) {
                newInId.add(replace.getWmsItemInventoryId());
            }
            if (oldInId.equals(newInId)) {
                //替换工作包
                msWorkbinMaterialDao.updateItemCodeInt((String) map.get("oldToolCode"), (String) map.get("newToolCode"));
                msWorkbinMaterialDao.updateItemCodeInt((String) map.get("newToolCode"), (String) map.get("oldToolCode"));
            } else {
                return "201";
            }
            //全部成功提交事务
            platformTransactionManager.commit(transaction);
            return "200";
        } catch (Exception e) {
            //有一个失败，回滚事务
            log.info(e.getMessage());
            platformTransactionManager.rollback(transaction);
            return e.getMessage();
        }
    }

    /***
     * 退库修改macth_info表退库数量，进行二次配套
     */
    public String returnToWarehouse(HashMap map) {
        String result = null;
        try {
            msAoMatchInfoDao.updateRetrunQty(map);
            result = "200";
        } catch (Exception e) {
            e.printStackTrace();
            result = "201";
        } finally {
            return result;
        }

    }

    //分拣占用
    @Transactional
    public String sortOccupy(String opUserCode, String IP, HashMap map) {
        JSONObject headersMap = new JSONObject();
        String msgId = CreatMsgId.getMsgId();
        //获取func
        headersMap.put("func", environment.getProperty("doReturnErp.sortOccupy.func"));
        headersMap.put("msgId", msgId);
        //分拣占用接口所需参数
        map.put("opUserCode", opUserCode);
        map.put("userIp", IP);
        map.put("taskNo", "");
        map.put("recHrDeptId", "");

        JSONObject data = new JSONObject(map);
        headersMap.put("data", data);
        String headersmap = headersMap.toJSONString();
        log.info("分拣占用上传ERP===============" + headersmap);
        //对已经转换成字符串的数据进行加密
        final Base64.Encoder encoder = Base64.getEncoder();
        String BData = encoder.encodeToString(headersmap.getBytes());
        log.info("==========================工控网上传_分拣占用============================");
        //工控网上传数据
        HashMap issuedTest = new HashMap();//originalId
        issuedTest.put("businessTab", "wms_inv_out_allotment");
        issuedTest.put("businessCol", "wms_inv_out_allotment_id");
        issuedTest.put("businessVal", map.get("originalId"));
        issuedTest.put("BData", headersmap);
        issuedTest.put("msgId", msgId);
        issuedTest.put("type", headersMap.get("func"));
        log.info("工控网上传程序后台日志:>>>>>>>>>>>>>>>>>>>>>>>>>issuedParameters:" + issuedTest.toString());
        log.info("==========================工控网上传_分拣占用============================");
        workService.issuedTest(issuedTest);
        return BData;
    }

    //分拣占用取消
    public String sortOccupyCancle(HashMap map) {
        try {
            Thread.sleep(10000);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        JSONObject headersMap = new JSONObject();
        String msgId = CreatMsgId.getMsgId();
        //获取func
        headersMap.put("func", environment.getProperty("doReturnErp.sortOccupCancel.func"));
        headersMap.put("msgId", msgId);
        //分拣占用接口所需参数
        map.put("opUserCode", map.get("opUserCode"));
        if (map.containsKey("IP")) {
            if (map.get("IP") == null || "".equals(map.get("IP"))) {
                map.put("userIp", "172.17.53.61");
            } else {
                map.put("userIp", map.get("IP"));
            }
        } else {
            map.put("userIp", "172.17.53.61");
        }

        JSONObject data = new JSONObject(map);
        headersMap.put("data", data);
        String headersmap = headersMap.toJSONString();

        //对已经转换成字符串的数据进行加密
        final Base64.Encoder encoder = Base64.getEncoder();
        String BData = encoder.encodeToString(headersmap.getBytes());

        log.info("==========================工控网上传_分拣占用取消============================");
        //工控网上传数据
        HashMap issuedTest = new HashMap();
        issuedTest.put("BData", headersmap);
        issuedTest.put("businessVal", map.get("wmsInvOutAllotmentId"));
        issuedTest.put("businessCol", "wms_inv_out_allotment_id");
        issuedTest.put("businessTab", "wms_inv_out_allotment");
        issuedTest.put("type", headersMap.get("func"));
        issuedTest.put("msgId", msgId);

        log.info("工控网上传程序后台日志:>>>>>>>>>>>>>>>>>>>>>>>>>issuedParameters:" + issuedTest.toString());
        log.info("==========================工控网上传_分拣占用取消============================");
        workService.issuedTest(issuedTest);

        return BData;
    }

    //分拣出库取消
    public String sortInvOutCancle(HashMap map) {
        try {
            Thread.sleep(10000);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        JSONObject headersMap = new JSONObject();
        String msgId = CreatMsgId.getMsgId();
        //获取func
        headersMap.put("func", environment.getProperty("doReturnErp.sortInvOutCancel.func"));
        headersMap.put("msgId", msgId);
        //分拣占用接口所需参数
        map.put("opUserCode", map.get("opUserCode"));
        if (map.containsKey("IP")) {
            if (map.get("IP") == null || "".equals(map.get("IP"))) {
                map.put("userIp", "172.17.53.61");
            } else {
                map.put("userIp", map.get("IP"));
            }
        } else {
            map.put("userIp", "172.17.53.61");
        }

        JSONObject data = new JSONObject(map);
        headersMap.put("data", data);
        String headersmap = headersMap.toJSONString();

        //对已经转换成字符串的数据进行加密
        final Base64.Encoder encoder = Base64.getEncoder();
        String BData = encoder.encodeToString(headersmap.getBytes());

        log.info("==========================工控网上传_分拣占用取消============================");
        //工控网上传数据
        HashMap issuedTest = new HashMap();
        issuedTest.put("BData", headersmap);
        issuedTest.put("businessVal", map.get("wmsInvOutAllotmentId"));
        issuedTest.put("businessCol", "wms_inv_out_allotment_id");
        issuedTest.put("businessTab", "wms_inv_out_allotment");
        issuedTest.put("type", headersMap.get("func"));
        issuedTest.put("msgId", msgId);

        log.info("工控网上传程序后台日志:>>>>>>>>>>>>>>>>>>>>>>>>>issuedParameters:" + issuedTest.toString());
        log.info("==========================工控网上传_分拣占用取消============================");
        workService.issuedTest(issuedTest);

        return BData;
    }

    //物料入库时，大件货物插入大件区货架表
    @Transactional
    public int insertLocator(HashMap map) {
        return wmsItemInventoryDao.insertLocator(map);
    }

    //物料入库，回退交接单状态
    public ResponseMsg backDevlieryToReceive(List<HashMap> list, String ip) {
        ResponseMsg responseMsg = new ResponseMsg();
        TransactionStatus transaction = platformTransactionManager.getTransaction(transactionDefinition);
        try {

            for (HashMap map : list) {
                map.put("ip", ip);
                //0：判断当前交接单是否部分入库,已生成台账的不允许回退
                int cnt = wmsItemInventoryDao.queryDeliveryExistsInventory(map);
                if (cnt > 0) {
                    platformTransactionManager.rollback(transaction);
                    String msg = "交接单号为：" + map.get("deliveryPlanCode") + ",图号为：" + map.get("itemCode") + "已经生成台账，不能回退";
                    responseMsg.setRetCode("201").setMessage(msg);
                    return responseMsg;
                }
                //1:备份ms_workbin_rece_detail数据
                wmsItemInventoryDao.insertWorkbinReceDetailDel(map);
                //2:情况ms_workbin_rece_detail 表数据
                wmsItemInventoryDao.deleteWorkbinReceDetail(map);
                //3：回退交接单装
                wmsItemInventoryDao.updateDeliveryPlanStatus(map);
            }
            platformTransactionManager.commit(transaction);
            responseMsg.setRetCode("200").setMessage("恢复状态成功");
        } catch (Exception e) {
            platformTransactionManager.rollback(transaction);
            e.printStackTrace();
            responseMsg.setRetCode("201").setMessage("恢复状态异常");
        }
        return responseMsg;
    }

    //查询接收叫箱信息
    public List<HashMap> queryReceiveGkLog(String ip) {
        //1：查询ms_gk_log  父信息
        List<HashMap> parents = wmsItemInventoryDao.queryReceiveGkLog(ip);

        for (HashMap parent : parents) {
            //2:查询ms_workbin_rece_detail 找N  parent
            List<HashMap> children = wmsItemInventoryDao.queryReceDetail(parent, ip);
            parent.put("children", children);
        }
        return parents;
    }


    /***
     * 工作包替换
     * sourceData:要替换的工作包数据
     * targetData：被替换的工作包数据
     * **/
    @Transactional
    public ResponseMsg replacePackage(HashMap sourceData, HashMap targetData) {
        ResponseMsg responseMsg = new ResponseMsg();
        //校验被替换的工作包是否已分拣
        List<HashMap> sourceBillInfos = msWorkbinMaterialDao.querySourceMatchBills((String) sourceData.get("msTaskPackageId"));
        for (HashMap sourceBillInfo : sourceBillInfos) {
            //查询当前bill表对应的
            List<HashMap> targetBillList = msWorkbinMaterialDao.queryTargetMatchBill((String) targetData.get("msTaskPackageId"), (String) sourceBillInfo.get("msTaskAoId"));
            if (targetBillList.size() > 1 || targetBillList.size() == 0) {
                responseMsg.setRetCode("201").setMessage("源工作包下物料与目标工作包下物料不一致");
            } else {
                //写入映射关系表
                HashMap tmp = new HashMap();
                tmp.put("sourceTaskPackageId", targetData.get("msTaskPackageId"));
                tmp.put("targetTaskPackageId", targetData.get("msTaskPackageId"));
                tmp.put("sourceAoMatchBillId", sourceBillInfo.get("msAoMatchBillId"));
                tmp.put("targetAoMatchBillId", targetBillList.get(0).get("msAoMatchBillId"));
                tmp.put("sourceTaskAoId", sourceBillInfo.get("msTaskAoId"));
                tmp.put("targetTaskAoId", targetBillList.get(0).get("msTaskAoId"));
                msWorkbinMaterialDao.insertWorkpackageReplace(tmp);
            }
        }
        if ("201".equals(responseMsg.getRetCode())) {
            TransactionAspectSupport.currentTransactionStatus().setRollbackOnly();
            return responseMsg;
        }
        if ("02".equals(sourceData.get("sortingStatus"))) {//源工作包已分拣
            //1:替换wm_workbin_material 表数据

            //2：替换占用表信息

        } else {//未分拣

        }
        //3:替换 match_info数据
        //3：更改task_ao数据

        //4：更改task_package数据
        return null;
    }

}
